home *** CD-ROM | disk | FTP | other *** search
/ Mastering Internet Develo…oft ActiveX Technologies / Mastering Internet Development with ActiveX (1996)(Microsoft).iso / labs / lab06 / redir / redirect.c < prev   
Encoding:
C/C++ Source or Header  |  1996-07-16  |  8.1 KB  |  224 lines

  1. // redir.dll
  2. //this isapi app is used to wisk the client away to a new
  3. //location and log the transaction.  redir.dll can be used
  4. //in one of two ways
  5. //
  6. //1.    <A HREF="redir.dll?target=http://www.volcanocoffee.com/">
  7. //      <IMG SRC="Volcano.gif"></A>
  8. //
  9. //
  10. //2. <FORM ACTION="redir.dll">
  11. //    <SELECT NAME="Target">  <!-- Name must be target -->
  12. //      <OPTION VALUE="http://www.volcanocoffee.com/">Volcano Coffee
  13. //      <OPTION VALUE="/some/local/path.htm">Local Path
  14. //   </SELECT>
  15. //   <INPUT TYPE="SUBMIT" VALUE="Go!">
  16. //  </FORM>
  17. //
  18. //local paths must being with '/'.  all other paths generate
  19. //an http 302 event.  redir.dll logs both the referring page
  20. //and the target page.  this allows the server admin to parse
  21. //the log file and give 'credit' to any pages containing 
  22. //advertisements.
  23.  
  24. #include <windows.h>
  25. #include <stdio.h>
  26. #include <httpext.h>
  27.  
  28. //Function Prototypes
  29. INT GetValueFromHex (CHAR);
  30. DWORD Redirect(CHAR *, EXTENSION_CONTROL_BLOCK *);
  31.  
  32.  
  33. BOOL WINAPI GetExtensionVersion (HSE_VERSION_INFO  *version)
  34. {
  35.     version->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR,
  36.                                             HSE_VERSION_MAJOR );
  37.     strcpy( version->lpszExtensionDesc,
  38.             "Redirect to another page" );
  39.  
  40.     return TRUE;
  41. }
  42.  
  43. //
  44. //
  45. //
  46.  
  47. DWORD WINAPI HttpExtensionProc (LPEXTENSION_CONTROL_BLOCK lpEcb)
  48. {
  49.       DWORD     dwRetCode;              //holds this request's status
  50.       CHAR      szBuff[2048];           //holds either the target var
  51.                                         //or the returning HTML data.
  52.       BOOL      done = FALSE;           //flag used in query string parsing
  53.       INT       i, j;                   //counters used in query string parsing
  54.       DWORD     dwLen;                  //used to hold length for server calls
  55.       CHAR      szReferer[MAX_PATH];    //used to hold the HTTP_REFERER variable
  56.       CHAR      szLogLine[MAX_PATH];    //used to hold the data we write to the log file
  57.   
  58.     //check request method, as we only support the GET method
  59.     if (stricmp (lpEcb->lpszMethod, "GET") == 0)
  60.     {    
  61.         //look for the target variable in the query string
  62.         if (strnicmp (lpEcb->lpszQueryString, "target=", 7) == 0)
  63.         {
  64.             i = 7;
  65.             j = 0;
  66.  
  67.             //parse query string to extract the value of the target
  68.             //variable.  this loop expands the %XX escapes via the
  69.             //GetValueFromHex function.  we parse the query string
  70.             //until we see a '&' char, indicating the end of the
  71.             //target variable, or until we see the end of the query
  72.             //string.
  73.             while ((done == FALSE) && (lpEcb->lpszQueryString[i] != '\0'))
  74.             {
  75.                 if (lpEcb->lpszQueryString[i] == '%')
  76.                 {
  77.                     szBuff[j++] = (GetValueFromHex (lpEcb->lpszQueryString[i+1]) * 16) +
  78.                                                     GetValueFromHex (lpEcb->lpszQueryString[i+2]);
  79.                     //skip past %XX escape
  80.                     i += 3;
  81.                 }
  82.                 else if (lpEcb->lpszQueryString[i] == '&')
  83.                 {
  84.                     done = TRUE;
  85.                 }
  86.                 else
  87.                 {
  88.                     szBuff[j++] = lpEcb->lpszQueryString[i++];
  89.                 }
  90.             }
  91.  
  92.             szBuff[j] = '\0';
  93.         
  94.             //get the HTTP_REFERER from the server.  if the
  95.             //client did not set the HTTP_REFERER variable,
  96.             //then set it to '-'.
  97.             dwLen = MAX_PATH;
  98.             if (!lpEcb->GetServerVariable(  lpEcb->ConnID, 
  99.                                             "HTTP_REFERER", 
  100.                                             szReferer, 
  101.                                             &dwLen))                                          
  102.             {
  103.                 strcpy (szReferer, "-");
  104.             }
  105.             
  106.             //build the string that we want to add to the log
  107.             //file.  it has the form " rdrRef=URL rdrTgt=URL"
  108.  
  109.             strcpy (szLogLine, " rdrRef=");
  110.             strcat (szLogLine, szReferer);
  111.             strcat (szLogLine, " rdrTgt=");
  112.             strcat (szLogLine, szBuff);
  113.  
  114.             //as an ISAPI Server Extension, we have only HSE_LOG_BUFFER_LEN
  115.             //chars (80 chars as of 7 feb 1996) to play with, so we copy
  116.             //HSE_LOG_BUFFER_LEN chars into the lpEcb->lpszLogData buffer.
  117.  
  118.             strncpy (lpEcb->lpszLogData, szLogLine, HSE_LOG_BUFFER_LEN -1);
  119.             lpEcb->lpszLogData[HSE_LOG_BUFFER_LEN -1] = '\0';
  120.             
  121.             //call the function that will do the redirection
  122.             dwRetCode = Redirect (szBuff, lpEcb);
  123.         }
  124.         else
  125.         {
  126.             //we could not find the target variable in the query string
  127.             //so we send the client a nicely formatted error message.
  128.             //we send the header "200 OK" to ensure that the client
  129.             //will display the text we are sending.
  130.  
  131.             wsprintf (szBuff,   "Content-Type: text/html\r\n"
  132.                                 "\r\n"
  133.                                 "<HTML>\n<HEAD>\n<TITLE>Unknown error.</TITLE>\n</HEAD>\n"
  134.                                 "<BODY>\n<H1>Unknown error.</H1>\n"
  135.                                 "Page parameter not found.",
  136.                                 "</BODY></HTML>");
  137.  
  138.             lpEcb->ServerSupportFunction (  lpEcb->ConnID,
  139.                                             HSE_REQ_SEND_RESPONSE_HEADER,
  140.                                             "200 OK",
  141.                                             NULL,
  142.                                             (LPDWORD) szBuff);
  143.             //we set the status to HSE_STATUS_ERROR tell the server
  144.             //that something went wrong.
  145.  
  146.             dwRetCode = HSE_STATUS_ERROR;
  147.         }
  148.  
  149.  
  150.  
  151.     }
  152.     else 
  153.     {
  154.         //request method not GET, so we send back a nicely formatted
  155.         //error message to tell the client what request method
  156.         //we support.
  157.             wsprintf (szBuff,   "Content-Type: text/html\r\n"
  158.                                 "\r\n"
  159.                                 "<HTML>\n<HEAD>\n<TITLE>Request Method Not Supported</TITLE>\n</HEAD>\n"
  160.                                 "<BODY>\n<H1>Request Method Not Supported</H1>\n"
  161.                                 "This ISAPI extension only supports the GET method.",
  162.                                 "</BODY></HTML>");
  163.  
  164.             lpEcb->ServerSupportFunction (  lpEcb->ConnID,
  165.                                             HSE_REQ_SEND_RESPONSE_HEADER,
  166.                                             "200 OK",
  167.                                             NULL,
  168.                                             (LPDWORD) szBuff);
  169.             dwRetCode = HSE_STATUS_ERROR;
  170.  
  171.     }    
  172.     return dwRetCode;
  173. }
  174.    // end HttpExtensionProc
  175.  
  176.  
  177. INT GetValueFromHex (CHAR ch)
  178. //
  179. //this function takes a char and returns the integer value
  180. //of the char interpreted as a HEX digit.  this function
  181. //expects the chars '0'-'9', 'a'-'f', or 'A'-'Z'.  if it
  182. //receives any other char, it returns -1.
  183.  
  184. {
  185.     if ( (ch >= '0') && (ch <= '9') )
  186.         return (ch - '0');
  187.     else if ( (ch >= 'a') && (ch <= 'f') )
  188.         return (ch - 'a' + 10);
  189.     else if ( (ch >= 'A') && (ch <= 'F') )
  190.         return (ch - 'A' + 10);
  191.     
  192.     return (-1);
  193. }
  194.  
  195. DWORD Redirect(CHAR * szRedir, EXTENSION_CONTROL_BLOCK *pECB) {
  196.     //this function actually does the redirection.  if szRedir begins with a
  197.     //'/' then it is a local URL and we use HSE_REQ_SEND_URL to send the
  198.     //file.  otherwise, we assume that szRedire contains a remote URL and we
  199.     //use HSE_REQ_SEND_URL_REDIRECT_RESP to generate an HTTP 302 redirection
  200.     //message.
  201.  
  202.     if (szRedir[0] == '/')
  203.     {
  204.         pECB->ServerSupportFunction(    pECB->ConnID,
  205.                                         HSE_REQ_SEND_URL,
  206.                                         szRedir,
  207.                                         (LPDWORD) sizeof(szRedir),
  208.                                         NULL);
  209.     }
  210.     else 
  211.     {
  212.         pECB->ServerSupportFunction(    pECB->ConnID,
  213.                                         HSE_REQ_SEND_URL_REDIRECT_RESP,
  214.                                         szRedir,
  215.                                         (LPDWORD) sizeof(szRedir),
  216.                                         NULL);
  217.  
  218.     }
  219.     return HSE_STATUS_SUCCESS;
  220. } //end redirect()
  221.  
  222.  
  223.  
  224.